package com.xjscrm.server.service.qywxcallback.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.uzai.mobile.collect.api.MicaTopics;
import com.uzai.mobile.collect.api.dto.MicaTriggerDto;
import com.uzai.mobile.collect.api.dto.trigger.MicaTriggerChangeLabelMsg;
import com.uzai.mobile.collect.api.enums.MicaTriggerType;
import com.xjscrm.common.annotation.MerId;
import com.xjscrm.common.entity.*;
import com.xjscrm.common.enums.DeviceTypeEnum;
import com.xjscrm.common.enums.RedisCacheKeyEnum;
import com.xjscrm.common.utils.DateUtil;
import com.xjscrm.common.utils.Tools;
import com.xjscrm.common.utils.ww.WwApiUtil;
import com.xjscrm.common.utils.ww.dto.WwCustomerResultDTO;
import com.xjscrm.server.biz.RatelimitService;
import com.xjscrm.server.biz.mq.producer.SendMsgProducer;
import com.xjscrm.server.common.util.DeviceTools;
import com.xjscrm.server.constant.Const;
import com.xjscrm.server.dto.wwcorpcallback.WwCorpCallbackQuery;
import com.xjscrm.server.mapper.*;
import com.xjscrm.server.service.common.CorpApplicationDeviceService;
import com.xjscrm.server.service.device.WwDeviceInfoService;
import com.xjscrm.server.service.grouppull.GroupPullConfigService;
import com.xjscrm.server.service.qywxcallback.QywxCallbackService;
import com.xjscrm.server.service.soptask.SopJobTagService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author liuqi
 * @date 2021年08月25日 20:17
 */
@Service
@Slf4j
public class QywxCallBackServiceImpl implements QywxCallbackService {

    @Autowired
    private WwCorpMapper wwCorpMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private WwDeviceMapper wwDeviceMapper;
    @Autowired
    private WwCustomerTagsUseridMapper wwCustomerTagsUseridMapper;
    @Autowired
    private WwCustomerMapper wwCustomerMapper;
    @Autowired
    private WwTagsUseridMapper wwTagsUseridMapper;
    @Autowired
    private SendMsgProducer sendMsgProducer;
    @Autowired
    private WwTagsMapper wwTagsMapper;
    @Autowired
    private WwCustomerTagsMapper wwCustomerTagsMapper;
    @Autowired
    private SopJobTagService sopJobTagService;
    @Autowired
    private WwCorpCallbackMapper wwCorpCallbackMapper;
    @Autowired
    private RatelimitService ratelimitService;
    @Autowired
    private CorpApplicationDeviceService corpApplicationDeviceService;
    @Autowired
    private WwDeviceInfoService wwDeviceInfoService;
    @Resource
    private GroupPullConfigService groupPullConfigService;

    /**
     * 处理企业微信回调
     *
     * @param
     * @return null
     * @author liuqi
     * @date 2021/8/13 11:38
     */
    @Async("taskExecutorForQywxCallback")
    public void qywxCallbackInserData(@MerId Long merId, String entId, String externalUserId) {

        log.info("-----企业开放平台回调----merId={}, corpId={}，externalUserId={}", merId, entId, externalUserId);

        //判断此时是否正在推送开放平台的企业标签
        String qywxCallbackInserDataKey = "qywxCallbackInserDataKey" + "_" + merId + entId + externalUserId;
        Object push_open_qytag_object = redisTemplate.opsForValue().get(qywxCallbackInserDataKey);
        if (push_open_qytag_object != null) {
            return;
        }

        try {
            //防止同步操作
            redisTemplate.opsForValue().set(qywxCallbackInserDataKey, qywxCallbackInserDataKey, 10, TimeUnit.SECONDS);
            int now = DateUtil.getTime();
            WwCorpCallback wwCorpCallback = wwCorpCallbackMapper.selectByMerIdAndEntIdAndExternalUserid(merId, entId, externalUserId);
            if (wwCorpCallback == null) {
                wwCorpCallback = new WwCorpCallback();
                wwCorpCallback.setId(IdWorker.getId());
                wwCorpCallback.setMerId(merId);
                wwCorpCallback.setEntId(entId);
                wwCorpCallback.setExternalUserid(externalUserId);
                wwCorpCallback.setCreateTime(now);
                wwCorpCallback.setUpdateTime(now);
                wwCorpCallbackMapper.insert(wwCorpCallback);
            }
        } catch (Exception e) {
            log.info(e.getMessage(), e);
        } finally {
            //清除判断正在通过外部账号更新标签缓存
            redisTemplate.delete(qywxCallbackInserDataKey);
        }
    }

    /**
     * 处理企业微信回调
     *
     * @param
     * @return null
     * @author liuqi
     * @date 2021/8/13 11:38
     */
    @Async("taskExecutorForQywxCallback")
    public void handerQywxCallbackByXxlJob(@MerId Long merId) {
        log.info("-----处理企业第三方平台回调线程----merId={}", merId);
        try {

            //允许执行总数
            Integer reFreshWxcontactsNum = Const.para.HANDER_QYCORP_CALLBACK_NUM;
            if (reFreshWxcontactsNum == null) {
                reFreshWxcontactsNum = 10; //默认10个
            }

            WwCorpCallbackQuery wwCorpCallBackQuery_ing = new WwCorpCallbackQuery();
            wwCorpCallBackQuery_ing.setStatus(1); //查询进行中的任务个数
            Integer count_ing = Tools.getInteger(wwCorpCallbackMapper.findCount(wwCorpCallBackQuery_ing));
            if (count_ing >= reFreshWxcontactsNum) { //最多只允许有10个进行中的任务刷新
                return;
            }

            int size = reFreshWxcontactsNum - count_ing; //保证进行中的总数固定，故本次执行个数为允许总数减去正在运行的总数
            //查询当前所有的订单拉取记录
            WwCorpCallbackQuery wwCorpCallBackQuery_notstart = new WwCorpCallbackQuery();
            wwCorpCallBackQuery_notstart.setStatus(0);
            Page<WwCorpCallback> page = new Page<>();
            page.setCurrent(1);//只查第一页
            page.setSize(size); //每页查询数
            page.addOrder(OrderItem.asc("id"));//默认id升序
            Long idStart = 0L;
            List<WwCorpCallback> wwCorpCallbackList = wwCorpCallbackMapper.findByList(page, wwCorpCallBackQuery_notstart);
            if (wwCorpCallbackList != null && wwCorpCallbackList.size() > 0) {
                //先将这查询出来的修改成状态
                for (WwCorpCallback wwCorpCallback : wwCorpCallbackList) {
                    wwCorpCallback.setStatus(1); //修改中
                    wwCorpCallbackMapper.updateStatusById(wwCorpCallback);
                }

                for (WwCorpCallback wwCorpCallback : wwCorpCallbackList) {
                    //限流判断
                    String handerQywxCallbackRateLimitKey = "handerQywxCallback-id=" + wwCorpCallback.getId();
                    try {
                        Object push_open_qytag_object = redisTemplate.opsForValue().get(handerQywxCallbackRateLimitKey);
                        if (push_open_qytag_object != null) {
                            return;
                        }
                        redisTemplate.opsForValue().set(handerQywxCallbackRateLimitKey, handerQywxCallbackRateLimitKey, 100, TimeUnit.SECONDS);

                        String entId = wwCorpCallback.getEntId();

                        WwCorp wwCorp = wwCorpMapper.selectByEntId(merId, entId);
                        if (wwCorp == null) {
                            log.info("未找到企业开放平台, merId={}, entId={}", merId, wwCorpCallback.getEntId());
                        }

                        if (StringUtils.isBlank(wwCorp.getEntSecret()) || StringUtils.isBlank(wwCorp.getEntToken())) {
                            log.info("企业开放平台信息不完整,merId={}, entId={}, entSecret={}, entToken={}", merId, entId, wwCorp.getEntSecret(), wwCorp.getEntToken());
                        }

                        //获取缓存
                        String accessToken = WwApiUtil.getAccessToken(entId, wwCorp.getEntSecret());
                        if (StringUtils.isBlank(accessToken)) {
                            log.info("未获取到第三方开放平台,merId={}, entId={}", wwCorpCallback.getMerId(), entId);
                            return;
                        }

                        //获取外部会员详情
                        WwCustomerResultDTO customerDetail = WwApiUtil.getCustomerDetail(accessToken, wwCorpCallback.getExternalUserid(), null);
                        if (customerDetail != null) {
                            handerWwCustomerResultDTO(merId, entId, customerDetail);
                            Integer next_cursor = customerDetail.getNext_cursor();
                        }

                    } catch (Exception e) {
                        log.info(e.getMessage(), e);
                    } finally {
                        //保存成功之后，手动删除限流redisKey
                        redisTemplate.delete(handerQywxCallbackRateLimitKey);
                        //删除该回调对象
                        wwCorpCallbackMapper.deleteById(wwCorpCallback.getId());
                    }
                }
            }
        } catch (Exception e) {
            log.info(e.getMessage(), e);
        } finally {

        }
    }


    /**
     * 处理企业微信回调
     *
     * @param
     * @return null
     * @author liuqi
     * @date 2021/8/13 11:38
     */
    @Async("taskExecutorForQywxCallback")
    public void handerQywxCallback(@MerId Long merId, String entId, String externalUserId) {

        log.info("-----进入企业微信回调线程----merId={}, corpId={}，externalUserId={}", merId, entId, externalUserId);

        try {
            int now = DateUtil.getTime();
            WwCorp wwCorp = wwCorpMapper.selectByEntId(merId, String.valueOf(entId));
            if (wwCorp == null) {
                log.info("未找到企业开放平台, merId={}, entId={}", merId, entId);
            }

            if (StringUtils.isBlank(wwCorp.getEntSecret()) || StringUtils.isBlank(wwCorp.getEntToken())) {
                log.info("企业开放平台信息不完整,merId={}, entId={}, entSecret={}, entToken={}", merId, entId, wwCorp.getEntSecret(), wwCorp.getEntToken());
            }

            //获取缓存
//            String qywxTokenKey = String.format(RedisCacheKeyEnum.QYWX_TOKEN.getKey(), entId);
//            String accessToken = (String) redisTemplate.opsForValue().get(qywxTokenKey);
//            if (StringUtils.isBlank(accessToken)) {
//                accessToken = WwApiUtil.getAccessToken(wwCorp.getEntId(), wwCorp.getEntSecret());
//                //存入缓存，保持2个小时
//                redisTemplate.opsForValue().set(qywxTokenKey, accessToken, 7200, TimeUnit.SECONDS);
//            }

            //获取缓存
            String accessToken = WwApiUtil.getAccessToken(wwCorp.getEntId(), wwCorp.getEntSecret());
            if (StringUtils.isBlank(accessToken)) {
                log.info("未获取到第三方开放平台,merId={}, entId={}", merId, entId);
                return;
            }

            //获取外部会员详情
            WwCustomerResultDTO customerDetail = WwApiUtil.getCustomerDetail(accessToken, externalUserId, null);
            if (customerDetail != null) {
                handerWwCustomerResultDTO(merId, entId, customerDetail);
                Integer next_cursor = customerDetail.getNext_cursor();
            } else {
                log.info("未获取到会员外部账号详情");
            }
        } catch (Exception e) {
            log.info(e.getMessage(), e);
        } finally {

        }
    }


    public void handerWwCustomerResultDTO(@MerId Long merId, String entId, WwCustomerResultDTO customerDetail) {

        log.info("进入获取会员详情方法， customerDetail={}", JSONObject.toJSONString(customerDetail));

        WwCustomerResultDTO.ExternalContact external_contact = customerDetail.getExternal_contact();
        if (external_contact != null) {
            List<WwCustomerResultDTO.FollowUser> followUsers = customerDetail.getFollow_user();
            if (followUsers != null || followUsers.size() > 0) {
                for (WwCustomerResultDTO.FollowUser followUser : followUsers) {
                    //判断机器人是否存在
                    if (StringUtils.isNotBlank(followUser.getUserid())) {
                        //通过服务商主体密文userid查询授权应用明文userid
                        CorpApplicationDevice corpApplicationDevice = corpApplicationDeviceService.selectByOpenuserId(followUser.getUserid());
                        if (corpApplicationDevice != null) {
                            //找到该机器人
                            WwDevice wwDevice = wwDeviceInfoService.selectById(corpApplicationDevice.getMerId(), corpApplicationDevice.getDeviceUniqueId());
                            if (wwDevice != null) {
                                List<WwCustomerResultDTO.TagItem> tags = followUser.getTags();
                                if (tags != null && tags.size() > 0) {
                                    //判断此标签是否还有获取会员外部id的标签。如果还有，则此次不做任何处理，只做通过会员外部id
                                    getCustomerExternalUserid(merId, wwDevice, external_contact, tags);
                                }
                                //同步标签
                                pushWwCustomerTags(merId, entId, wwDevice, external_contact, tags);
                            }
                        }
                    }
                }
            }
        }
    }

    //获取会员的外部id
    public void getCustomerExternalUserid(Long merId, WwDevice wwDevice, WwCustomerResultDTO.ExternalContact external_contact, List<WwCustomerResultDTO.TagItem> tags) {
        try {

            if (tags == null) {
                tags = new ArrayList<>();
            }

            for (WwCustomerResultDTO.TagItem tag : tags) {
                String tag_name = Tools.getStr(tag.getTag_name());
                if (tag_name.startsWith(Const.para.TAG_USERID)) {

                    log.info("-收到同步会员外部账号接口-tag_name={}", tag_name);

                    //查询会员
                    WwCustomerTagsUserid wwCustomerTagsUserid = wwCustomerTagsUseridMapper.queryByDeviceUniqueIdAndTagName(wwDevice.getId(), tag_name);
                    if (wwCustomerTagsUserid != null) {
                        WwCustomer wwCustomer = wwCustomerMapper.queryById(wwCustomerTagsUserid.getCustomerId());
                        if (wwCustomer != null) {
                            wwCustomer.setExternalUserid(external_contact.getExternal_userid());
                            wwCustomer.setExternalStatus(2);
                            wwCustomer.setUpdateTime(DateUtil.getTime());
                            wwCustomerMapper.updateExternalUserid(wwCustomer);

                            //删除此会员打的获取外部userid标签指令
                            wwCustomerTagsUseridMapper.deleteByCustomId(wwCustomer.getId());

                            //查询此标签
                            WwTagsUserid wwTagsUserid = wwTagsUseridMapper.queryByTagNameAndDeviceUniqueId(wwCustomer.getDeviceUniqueId(), tag_name);
                            if (wwTagsUserid != null) {
                                //删除此标签
                                wwTagsUseridMapper.deleteById(wwTagsUserid.getId());
                                //发送删除标签指令
                                MicaTriggerChangeLabelMsg micaTriggerChangeLabelMsg = new MicaTriggerChangeLabelMsg();
                                micaTriggerChangeLabelMsg.setLabelId(wwTagsUserid.getTagId());
                                micaTriggerChangeLabelMsg.setLabelName(wwTagsUserid.getTagName());
                                micaTriggerChangeLabelMsg.setMessageId(wwTagsUserid.getId());
                                MicaTriggerDto micaTriggerDto = MicaTriggerDto.newInstance(micaTriggerChangeLabelMsg, MicaTriggerType.TRIGGER_DEL_LABEL);
                                micaTriggerDto.setMerId(merId);
                                micaTriggerDto.setDeviceId(wwDevice.getDeviceId());
                                micaTriggerDto.setDeviceType(DeviceTypeEnum.DT_ANDROID_WORK_WECHAT_VALUE);
                                sendMsgProducer.pushMsg(micaTriggerDto, MicaTopics.WW_TRIGGER_TOPIC);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    //同步会员标签
    public void pushWwCustomerTags(Long merId, String entId, WwDevice wwDevice, WwCustomerResultDTO.ExternalContact external_contact, List<WwCustomerResultDTO.TagItem> tags) {

        //判断此时是否正在推送开放平台的企业标签
        String push_open_qytag_key = String.format(RedisCacheKeyEnum.PUSH_OPEN_QYTAG.getKey(), merId, entId);
        Object push_open_qytag_object = redisTemplate.opsForValue().get(push_open_qytag_key);
        if (push_open_qytag_object != null) {
            return;
        }

        //根据外部账号id和机器人查询该会员是否存在
        String external_userid = external_contact.getExternal_userid();

        //判断正在通过外部账号更新标签缓存
        String push_customer_tag_by_external_userid_key = String.format(RedisCacheKeyEnum.PUSH_CUSTOMER_TAG_BY_EXTERNAL_USERID.getKey(), wwDevice.getId(), external_userid);
        Object push_customer_tag_by_external_userid_object = redisTemplate.opsForValue().get(push_customer_tag_by_external_userid_key);
        if (push_customer_tag_by_external_userid_object != null) {
            return;
        }

        try {
            //正在通过外部账号更新标签缓存,防止同步操作
            redisTemplate.opsForValue().set(push_customer_tag_by_external_userid_key, external_userid, 300, TimeUnit.SECONDS);

            WwCustomer wwCustomer = wwCustomerMapper.queryByDeviceUniqueIdAndExternalUserid(wwDevice.getId(), external_userid);
            if (wwCustomer == null) {
                return;
            }

            //临时封装该企业的所有企业标签（找到一个一个则删除一个，剩下的表示不是微信中，数据库中多余的，则需要批量删除）
            List<WwTags> wwTagsList_enter = new ArrayList<>();

            List<WwCustomerTags> wwCustomerTagsList = wwCustomerTagsMapper.queryByCustomerId(wwCustomer.getId());
            if (wwCustomerTagsList != null && wwCustomerTagsList.size() > 0) {
                for (WwCustomerTags wwCustomerTags : wwCustomerTagsList) {
                    WwTags wwTags = wwTagsMapper.queryById(wwCustomerTags.getTagId());
                    if (wwTags != null && StringUtils.isNotBlank(wwTags.getExternalId())) {
                        wwTagsList_enter.add(wwTags);
                    }
                }
            }

            //是否成功打标签判断
            boolean addTagFlag = false;

            for (WwCustomerResultDTO.TagItem tag : tags) {
                //企业标签
                if (Tools.getInteger(tag.getType()).intValue() == 1) {

                    //从临时封装列表中删除该企微标签，最后剩下的表示此标签不在开放平台中，则需要统一删除
                    wwTagsList_enter.removeIf(item -> Objects.equals(tag.getTag_id(), item.getExternalId()));

                    //查询该企业标签是否存在
                    WwTags wwTags = wwTagsMapper.queryByExternalId(merId, wwDevice.getCorpId(), tag.getTag_id());
                    if (wwTags == null) {
                        //根据标签分组名称去查询分组是否存在
                        WwTags wwTagsGroup = wwTagsMapper.queryByGroupName(merId, wwDevice.getCorpId(), tag.getGroup_name());
                        if (wwTagsGroup == null) {//如果标签组不存在，则新建标签组
                            wwTagsGroup = new WwTags();
                            wwTagsGroup.setId(IdWorker.getId());
                            wwTagsGroup.setMerId(merId);
                            wwTagsGroup.setDeviceUniqueId(wwDevice.getId());
                            wwTagsGroup.setType(1);
                            wwTagsGroup.setTagId(null);
                            wwTagsGroup.setTagName(tag.getGroup_name());
                            wwTagsGroup.setPid(0L);
                            wwTagsGroup.setCorpId(wwDevice.getCorpId());
                            wwTagsGroup.setStatus(0);
                            wwTagsGroup.setSysGroup(0); //不默认
                            wwTagsGroup.setExternalId("");
                            wwTagsGroup.setCreateTime(DateUtil.getTime());
                            wwTagsGroup.setUpdateTime(DateUtil.getTime());
                            wwTagsMapper.insert(wwTagsGroup);
                        }
                        //标签新增加
                        wwTags = new WwTags();
                        wwTags.setId(IdWorker.getId());
                        wwTags.setMerId(merId);
                        wwTags.setDeviceUniqueId(wwDevice.getId());
                        wwTags.setType(1);
                        wwTags.setTagId(null);
                        wwTags.setTagName(tag.getTag_name());
                        wwTags.setPid(wwTagsGroup.getId());
                        wwTags.setCorpId(wwDevice.getCorpId());
                        wwTags.setStatus(0);
                        wwTags.setSysGroup(0); //不默认
                        wwTags.setExternalId(tag.getTag_id());
                        wwTags.setCreateTime(DateUtil.getTime());
                        wwTags.setUpdateTime(DateUtil.getTime());
                        wwTagsMapper.insert(wwTags);
                    }

                    if (wwTags != null) {
                        //查询此会员是否已经打上此标签，如果未打，则需要自动打
                        WwCustomerTags wwCustomerTags = wwCustomerTagsMapper.queryByCustomerIdAndTagId(wwCustomer.getId(), wwTags.getId());
                        if (wwCustomerTags == null) {//未找到，则需要打上此标签
                            wwCustomerTags = new WwCustomerTags();
                            wwCustomerTags.setId(IdWorker.getId());
                            wwCustomerTags.setTagId(wwTags.getId());
                            wwCustomerTags.setTagIdStr(wwTags.getExternalId());
                            wwCustomerTags.setCustomerId(wwCustomer.getId());
                            wwCustomerTags.setMerId(wwCustomer.getMerId());
                            wwCustomerTags.setCreateTime(DateUtil.getTime());
                            wwCustomerTags.setUpdateTime(DateUtil.getTime());
                            wwCustomerTagsMapper.insert(wwCustomerTags);
                            groupPullConfigService.groupPushByEnterpriseTag(DeviceTools.transDevice(wwDevice), wwCustomer, wwCustomerTags.getTagId());

                            addTagFlag = true;
                        }
                    }
                }
            }

            //剩下的表示数据库多余的,全部清除此会员标签
            for (WwTags wwTags_enter : wwTagsList_enter) {
                wwCustomerTagsMapper.deleteByCustomerIdAndTagId(wwCustomer.getId(), wwTags_enter.getId());
            }

            if (addTagFlag) {
                //触发SOP任务-自动打标签
                sopJobTagService.addSopJobByPushCustomerTag(merId, wwDevice, wwCustomer);
            }

        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            //清除判断正在通过外部账号更新标签缓存
            redisTemplate.delete(push_customer_tag_by_external_userid_key);
        }
    }

}
